<template>
    <div class="box">
        <!-- 面包屑导航区 -->
        <t-breadcrumb :maxItemWidth="'150'">
            <t-breadcrumbItem :to="{ path: '/dashboard' }">首页</t-breadcrumbItem>
            <t-breadcrumbItem>用户管理</t-breadcrumbItem>
            <t-breadcrumbItem :maxWidth="'160'">用户列表</t-breadcrumbItem>
        </t-breadcrumb>

        <!-- 卡片视图区域 -->
        <t-card bordered>
            <!-- 搜索与添加区域 -->
            <t-row :gutter="20">
                <t-col :span="5">
                    <div class="search">
                        <t-input v-model="queryInfo.query" clearable @clear="getUserList" :onEnter="getUserList"
                            placeholder="请输入内容"></t-input>
                        <t-button theme="default" @click="getUserList"> 搜索 <search-icon slot="icon" /> </t-button>
                    </div>
                </t-col>
                <t-col :span="1">
                    <t-button @click="addDialogVisible = true"> 添加用户</t-button>
                </t-col>
                <t-col :span="3">
                    <t-row>
                        <t-space>
                            <t-upload ref="uploadRef1" action v-model="files" :autoUpload="false" accept=".xlsx,.xls"
                                @select-change="handleExcel"></t-upload>
                            <t-button @click="exportExcel"> 导出数据</t-button>
                        </t-space>
                    </t-row>
                </t-col>
            </t-row>
            <!-- 用户列表区域 -->
            <t-table rowKey="id" :data="userList" :columns="columns" :selected-row-keys="selectedRowKeys"
                @select-change="rehandleSelectChange" reserve-selected-row-on-paginate stripe bordered hover resizable>
                <!-- 插槽方式 自定义单元格， colKey 的值默认为插槽名称  -->
                <template #mg_state="{ row }">
                    <t-switch size="large" v-model="row.mg_state" @change="userStateChanged(row)"></t-switch>
                </template>

                <!-- 插槽方式 自定义单元格， colKey 的值默认为插槽名称  -->
                <template #operate="{ row }">
                    <t-space>
                        <!-- 编辑按钮 -->
                        <t-button theme="primary" size="small" @click="showEditDialog(row.id)"><i
                                class="iconfont icon-bianji"></i></t-button>
                        <!-- 删除按钮 -->
                        <t-button theme="danger" size="small" @click="removeUserById(row.id)"><i
                                class="iconfont icon-shanchu"></i></t-button>
                        <!-- 分配角色按钮 -->
                        <t-button theme="warning" size="small" @click="setRole(row)"><i
                                class="iconfont icon-shezhi"></i></t-button>
                    </t-space>
                </template>

            </t-table>

            <!-- 分页 -->
            <t-pagination v-model="queryInfo.pagenum" :total="total" :pageSizeOptions="[1, 2, 5, 10]"
                :page-size.sync="queryInfo.pagesize" @current-change="onCurrentChange"
                @page-size-change="onPageSizeChange" />
        </t-card>

        <!-- 添加用户的对话框 -->
        <t-dialog header="添加用户" @close="addDialogClosed" :footer="false" :visible.sync="addDialogVisible">
            <t-form :data="addForm" ref="addFormRef" :rules="addFormRules" @submit="addUser">
                <!-- 主体区域 -->
                <t-form-item label="用户名" name="username">
                    <t-input v-model="addForm.username" placeholder="请输入用户名" />
                </t-form-item>
                <t-form-item label="密码" name="password">
                    <t-input type="password" v-model="addForm.password" placeholder="请输入密码"></t-input>
                </t-form-item>
                <t-form-item label="确认密码" name="rePassword">
                    <t-input type="password" v-model="addForm.rePassword" placeholder="请输入确认密码"></t-input>
                </t-form-item>
                <t-form-item label="邮箱" name="email">
                    <t-input v-model="addForm.email" placeholder="请输入邮箱" />
                </t-form-item>
                <t-form-item label="手机" name="mobile">
                    <t-input v-model="addForm.mobile" placeholder="请输入手机" />
                </t-form-item>
                <!-- 按钮区域 -->
                <template>
                    <div style="float: right">
                        <t-space>
                            <t-button theme="default" @click="addDialogClosed">取消</t-button>
                            <t-button theme="primary" type="submit">确定</t-button>
                        </t-space>
                    </div>
                </template>
            </t-form>
        </t-dialog>

        <!-- 修改用户的对话框 -->
        <t-dialog header="修改用户" @close="editDialogClosed" :footer="false" :visible.sync="editDialogVisible">
            <t-form :data="editForm" ref="editFormRef" :rules="editFormRules" @submit="editUserInfo">
                <!-- 主体区域 -->
                <t-form-item label="用户名" name="username">
                    <t-input v-model="editForm.username" disabled />
                </t-form-item>
                <t-form-item label="邮箱" name="email">
                    <t-input v-model="editForm.email" placeholder="请输入邮箱" />
                </t-form-item>
                <t-form-item label="手机" name="mobile">
                    <t-input v-model="editForm.mobile" placeholder="请输入手机" />
                </t-form-item>
                <!-- 按钮区域 -->
                <template>
                    <div style="float: right">
                        <t-space>
                            <t-button theme="default" @click="editDialogClosed">取消</t-button>
                            <t-button theme="primary" type="submit">确定</t-button>
                        </t-space>
                    </div>
                </template>
            </t-form>
        </t-dialog>

        <!-- 分配角色的对话框 -->
        <t-dialog header="分配角色" @close="setRoleDialogClosed" :footer="false" :visible.sync="setRoleDialogVisible">
            <t-form :data="userInfo" @submit="saveRoleInfo">
                <!-- 主体区域 -->
                <t-form-item label="当前的用户">
                    <t-input v-model="userInfo.username" disabled />
                </t-form-item>
                <t-form-item label="当前的角色">
                    <t-input v-model="userInfo.role_name" disabled />
                </t-form-item>
                <t-form-item label="分配新角色">
                    <t-select v-model="selectedRoleId" placeholder="请选择角色">
                        <t-option v-for="item in rolesList" :value="item.id" :label="item.roleName"
                            :key="item.id"></t-option>
                    </t-select>
                </t-form-item>
                <!-- 按钮区域 -->
                <template>
                    <div style="float: right">
                        <t-space>
                            <t-button theme="default" @click="setRoleDialogClosed">取消</t-button>
                            <t-button theme="primary" type="submit">确定</t-button>
                        </t-space>
                    </div>
                </template>
            </t-form>
        </t-dialog>
    </div>
</template>

<script>
import { SearchIcon, } from 'tdesign-icons-vue'
import { readFile, columnTable, formatDate } from '../../utils/utils'
import xlsx from "xlsx"
import { LoadingPlugin } from 'tdesign-vue'

export default {

    components: {
        SearchIcon
    },

    created() {
        this.getUserList()
    },

    data() {
        return {
            // 获取用户列表的参数对象
            queryInfo: {
                query: '',
                // 当前页数
                pagenum: 1,
                pagesize: 10,
            },
            // 用户列表
            userList: [],
            columns: [
                { colKey: 'row-select', type: 'multiple', width: '20' },
                { colKey: 'serial-number', width: 20, title: '序号' },
                { colKey: 'username', title: '姓名', width: '100' },
                { colKey: 'email', title: '邮箱', width: '100' },
                { colKey: 'mobile', title: '电话', width: '60' },
                { colKey: 'role_name', title: '角色', width: '60' },
                { colKey: 'mg_state', title: '状态', width: '35' },
                { colKey: 'operate', title: '操作', width: '65' },
            ],
            selectedRowKeys: [],
            selectedRowList: [],
            total: 0,
            // 控制添加用户对话框的显示与隐藏
            addDialogVisible: false,
            // 控制修改用户对话框的显示与隐藏
            editDialogVisible: false,
            // 控制分配角色对话框的显示与隐藏
            setRoleDialogVisible: false,
            // 添加用户的表单数据
            addForm: {
                username: '',
                password: '',
                rePassword: '',
                email: '',
                mobile: '',
            },
            // 查询到的用户信息对象
            editForm: {
            },
            // 添加表单的验证规则对象
            addFormRules: {
                username: [
                    {
                        required: true,
                        message: '请输入用户名',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '用户名不能为空' },
                    {
                        min: 2,
                        message: '至少需要两个字符，一个中文等于两个字符',
                        type: 'warning',
                        trigger: 'blur',
                    },
                    {
                        max: 10,
                        message: '用户名字符长度超出',
                        type: 'warning',
                        trigger: 'blur',
                    },
                ],
                password: [
                    {
                        required: true,
                        message: '请输入密码',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '密码不能为空' },
                    // 自定义校验规则：不同的值可以有不同的校验结果，不同的校验类型
                    { validator: this.passwordValidator },
                ],
                rePassword: [
                    {
                        required: true,
                        message: '请输入确认密码',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '确认密码不能为空' },
                    // 自定义校验规则：自定义异步校验规则
                    { validator: this.rePassword, message: '两次密码不一致' },
                ],
                email: [
                    {
                        required: true,
                        message: '请输入邮箱',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '邮箱不能为空' },
                    { validator: this.checkEmail, trigger: 'blur', },
                ],
                mobile: [
                    {
                        required: true,
                        message: '请输入手机',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '手机不能为空' },
                    { validator: this.checkMobile, trigger: 'blur', },
                ],

            },
            editFormRules: {
                email: [
                    {
                        required: true,
                        message: '请输入邮箱',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '邮箱不能为空' },
                    { validator: this.checkEmail, trigger: 'blur', },
                ],
                mobile: [
                    {
                        required: true,
                        message: '请输入手机',
                        type: 'error',
                        trigger: 'blur',
                    },
                    { whitespace: true, message: '手机不能为空' },
                    { validator: this.checkMobile, trigger: 'blur', },
                ],
            },

            // 需要被分配角色的用户信息
            userInfo: {},

            // 所有角色的数据列表
            rolesList: [],

            // 已选中的角色Id值
            selectedRoleId: '',

            // 表格文件上传
            files: [],
        }
    },
    methods: {
        // 获取用户列表
        async getUserList() {

            const { data: res } = await this.$http.get('users', { params: this.queryInfo })
            if (res.meta.status !== 200) {
                this.$message.error('获取用户列表失败！')
            } else {

                this.userList = res.data.users

                this.total = res.data.total
            }
        },


        // 每页数量切换时触发
        onPageSizeChange(size, pageInfo) {
            this.queryInfo.pagesize = size
            this.getUserList()
        },

        // 页码值切换时触发
        onCurrentChange(current, pageInfo) {
            this.queryInfo.pagenum = current
            this.getUserList()
        },

        // 修改用户状态
        async userStateChanged(userInfo) {
            const { data: res } = await this.$http.put(`users/${userInfo.id}/state/${userInfo.mg_state}`)
            if (res.meta.status !== 200) {
                userInfo.mg_state = !userInfo.mg_state
                this.$message.error('更新用户状态失败！')
            } else {
                this.$message.success('更新用户状态成功！')
            }
        },

        // 自定义校验器，不同的值输出不同的校验结果。支持异步校验（文案选自某密码重置站点，如有侵权，请联系我们删除）
        passwordValidator(val) {
            if (val.length > 0 && val.length <= 2) {
                return { result: false, message: '太简单了！再开动一下你的小脑筋吧！', type: 'error' };
            }
            if (val.length > 2 && val.length < 4) {
                return { result: false, message: '还差一点点，就是一个完美的密码了！', type: 'warning' };
            }
            return { result: true, message: '太强了，你确定自己记得住吗！', type: 'success' };
        },
        // 自定义异步校验器
        rePassword(val) {
            return new Promise((resolve) => {
                const timer = setTimeout(() => {
                    resolve(this.addForm.password === val);
                    clearTimeout(timer);
                });
            });
        },

        // 验证邮箱的规则
        checkEmail(val) {
            const regEmail = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/

            if (!regEmail.test(val)) {
                return { result: false, message: '请输入合法的邮箱', type: 'error' };
            }
            return { result: true, message: '邮箱可用', type: 'success' };

        },

        // 验证手机号的规则
        checkMobile(val) {
            const regMobile = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
            if (!regMobile.test(val)) {
                return { result: false, message: '请输入合法的手机号', type: 'error' };
            }
            return { result: true, message: '手机号可用', type: 'success' };
        },

        // 监听添加用户对话框的关闭事件
        addDialogClosed() {
            this.addDialogVisible = false
            this.$refs.addFormRef.reset()
        },
        // 点击按钮，添加新用户
        async addUser({ validateResult, firstError }) {
            if (validateResult === true) {
                const { data: res } = await this.$http.post('users', this.addForm)
                if (res.meta.status !== 201) {
                    this.$message.error('添加用户失败！')
                } else {
                    this.$message.success('添加用户成功！')
                    // 隐藏添加用户的对话框
                    this.addDialogVisible = false
                    // 重新获取用户列表数据
                    this.getUserList()
                }
            } else {
                this.$message.warning(firstError);
            }
        },
        // 展示编辑用户的对话框
        async showEditDialog(id) {
            const { data: res } = await this.$http.get('users/' + id)
            if (res.meta.status !== 200) {
                this.$message.error('查询用户信息失败！')
            } else {
                this.editForm = res.data
                this.editDialogVisible = true
            }
        },

        // 监听修改用户对话框的关闭事件
        editDialogClosed() {
            this.editDialogVisible = false
            this.$refs.editFormRef.reset()
        },

        // 修改用户信息并提交
        async editUserInfo({ validateResult, firstError }) {
            if (validateResult === true) {
                const { data: res } = await this.$http.put('users/' + this.editForm.id, {
                    email: this.editForm.email,
                    mobile: this.editForm.mobile
                })

                if (res.meta.status !== 200) {
                    this.$message.error('更新用户信息失败！')
                } else {
                    this.$message.success('更新用户信息成功！')
                    // 重新获取用户列表数据
                    this.getUserList()
                    // 隐藏编辑用户的对话框
                    this.editDialogVisible = false
                }
            } else {
                this.$message.warning(firstError);
            }
        },

        // 根据Id删除对应的用户信息
        removeUserById(id) {
            // 弹窗询问用户是否删除数据
            const confirmDia = this.$dialog.confirm({
                header: '提示',
                body: '次操作将永久删除该用户，是否继续？',
                confirmBtn: '确定',
                cancelBtn: '取消',
                onConfirm: async ({ e }) => {
                    // console.log('confirm button has been clicked!');
                    // console.log('e: ', e);
                    const { data: res } = await this.$http.delete('users/' + id)
                    if (res.meta.status !== 200) {
                        this.$message.error('删除用户失败！')
                    } else {
                        this.getUserList()
                        this.$message.success('删除用户成功！')
                        // 请求成功后，销毁弹框
                        confirmDia.destroy();
                    }
                },
                onClose: ({ e, trigger }) => {
                    this.$message.info('已取消删除')
                    // console.log('e: ', e);
                    // console.log('trigger: ', trigger);
                    confirmDia.hide();
                },
            })
        },

        // 展示分配角色的对话框
        async setRole(userInfo) {
            this.userInfo = userInfo

            // 在展示对话框之前获取所有角色列表
            const { data: res } = await this.$http.get('roles')

            if (res.meta.status !== 200) {
                this.$message.error('获取角色列表失败！')
            } else {
                this.rolesList = res.data
                this.setRoleDialogVisible = true

            }

        },

        // 点击按钮 分配角色
        async saveRoleInfo() {
            if (!this.selectedRoleId) {
                this.$message.error('请选择要分配的角色！')
            } else {
                const { data: res } = await this.$http.put(`users/${this.userInfo.id}/role`, { rid: this.selectedRoleId })

                if (res.meta.status !== 200) {
                    this.$message.error('更新角色失败！')
                } else {
                    this.$message.success('更新角色成功！')
                    this.getUserList()
                    this.setRoleDialogVisible = false
                }
            }

        },

        // 监听分配角色对话框的关闭事件
        setRoleDialogClosed() {
            this.setRoleDialogVisible = false
            this.selectedRoleId = ''
            this.userInfo = {}
        },

        // 采集 EXCEL 数据
        async handleExcel(files) {
            let file = files[0] // ev 为上传的文件数据
            if (!file) return

            // 1. 读取FILE中的数据为二进制数据
            let data = await readFile(file)

            // 2. 处理二进制数据为Excel文件
            let workbook = xlsx.read(data, { type: "binary" })

            // 3. 拿到 Excel 第一张表
            let worksheet = workbook.Sheets[workbook.SheetNames[0]]

            // 4. 解析为json数据
            data = xlsx.utils.sheet_to_json(worksheet)

            // 5. 把读取出来的数据变为最后可以传递给服务器的数据 (姓名=>name 电话=>phone)
            let arr = []

            data.forEach(item => {
                let obj = {}

                // 遍历字段表中的属性
                for (let key in columnTable) {

                    // 如果遍历完了就退出循环
                    if (!columnTable.hasOwnProperty(key)) break

                    // 拿到字段表中的第一个字段对象
                    let columnObj = columnTable[key] // {text: '姓名',type: 'string'},

                    // 取出该字段的名称和类型
                    let text = columnObj.text // 姓名
                    let type = columnObj.type // string

                    // 取出该字段对应的值 如果不存在则为空
                    let value = item[text] || "" // 王飞龙

                    // 根据数据类型进行格式化处理
                    type === "string" ? value = String(value) : null
                    type === "number" ? value = Number(value) : null

                    obj[key] = value
                }

                arr.push(obj)
            })

        },

        // 表格选中项变化时触发
        rehandleSelectChange(value, { selectedRowData }) {
            this.selectedRowKeys = value;
            this.selectedRowList = selectedRowData
        },

        // 导出表格数据为 Excel
        exportExcel() {
            if (this.selectedRowKeys.length <= 0) {
                return this.$message.warning('请您先选择要导出的数据哦！')
            }

            // 开启加载
            const loading = LoadingPlugin({
                fullscreen: true,
                attach: 'body',
                preventScrollThrough: true,
            })

            // 筛选出要导出的字段并格式化为中文
            let data = this.selectedRowList.map(item => {
                return {
                    姓名: item.username,
                    邮箱: item.email,
                    电话: item.mobile
                }
            })

            console.log(data);

            // 将json转为sheet表格
            let sheet = xlsx.utils.json_to_sheet(data)
            // 创建 book 文件 => excel
            let book = xlsx.utils.book_new()
            // 将sheet追加到book中
            xlsx.utils.book_append_sheet(book, sheet, '用户信息表')
            // 下载文件，并格式化命名
            console.log(formatDate(new Date().getTime()));
            xlsx.writeFile(book, `学生档案信息${formatDate(new Date().getTime())}.xlsx`)

            // 隐藏加载图标
            loading.hide()
        },



    },
}
</script>

<style lang="less" scoped>
.box {
    padding: 15px;

    .search {
        display: flex;
        justify-content: center;
    }
}
</style>